package com.gitee.wsl.ext.base

import com.gitee.wsl.ext.array.bytes.updateUseLittleEndian
import com.gitee.wsl.lang.ByteOrder

typealias Integer = Int

val Int.Companion.SIZE: Int
    get() = Int.SIZE_BITS

val Int.Companion.BYTES: Int
    get() = Int.SIZE_BYTES


fun Int.indexToNumber() = this + 1

fun Int.numberToIndex() = this - 1

//幂
/** Returns the next power of two of [this] */
val Int.nextPowerOfTwo: Int get() {
    var v = this
    v--
    v = v or (v shr 1)
    v = v or (v shr 2)
    v = v or (v shr 4)
    v = v or (v shr 8)
    v = v or (v shr 16)
    v++
    return v
}
/** Checks if [this] value is power of two */
//val Int.isPowerOfTwo: Boolean get() = this.nextPowerOfTwo == this
val Int.isPowerOfTwo: Boolean get() = this == 1 /*2^0=1*/ || ((this > 0) && ((this and (this - 1)) == 0))

/** Returns the previous power of two of [this] */
val Int.prevPowerOfTwo: Int get() = if (isPowerOfTwo) this else (nextPowerOfTwo ushr 1)

//素数
/** Checks if [this] is odd (not multiple of two) */
val Int.isOdd: Boolean get() = (this % 2) == 1

/** Checks if [this] is even (multiple of two) */
val Int.isEven: Boolean get() = (this % 2) == 0


/** Like QuickJS' `bc_get_flags` where n is > 1. */
@Suppress("NOTHING_TO_INLINE") // Syntactic sugar.
inline fun Int.bits(bit: Int, bitCount: Int): Int {
    return (this ushr bit) and ((1 shl bitCount) - 1)
}

/** support shift */
fun Int.circleIndex(len: Int = 26, shift: Int = 0) =
    with(this + shift) { if (this < 0) (this % len + len) else this } % len

//素数
fun Int.isPrime():Boolean = this > 1 && (2 until this).none{ this % it == 0}

/*fun Int.isPrime(): Boolean {
    if (this == 1) return false
    if (this == 2) return true
    if (this % 2 == 0) return false
    for (i in 3..sqrt(this.toDouble()).toInt() step 2) {
        if (this % i == 0) return false
    }
    return true
}*/

/**
 * Checks if an Int value is a prime number.
 *
 * @return `true` if the Int value is a prime number, `false` otherwise.
 */
//fun Int.isPrime(): Boolean {
//    if (this < 2) {
//        return false
//    }
//    val root = kotlin.math.sqrt(this.toDouble()).toInt()
//    for (divisor in EVEN_DIVISOR..root) {
//        if (this % divisor == 0) {
//            return false
//        }
//    }
//    return true
//}


/**
 * OR the byte to the submitted position in the current bigEndianInteger
 * if byte is 0xB and the current int (this) is 0xAAAA then:
 * 0xAAAA.buildFrom(0xB, 2) => 0xAABA.
 * Byte position must be between 0 and [Int.SIZE_BYTES]
 */
fun Int.buildFrom(byte: Byte, bytePosition: Int): Int {
    require(bytePosition <= Int.SIZE_BYTES) {
        "This byte position must be between 0 and ${Int.SIZE_BYTES}"
    }

    return this.or(byte.and(0xF).shl(bytePosition))
}


/**
 * Converts an [Int] to an array of [Byte] using the big-endian conversion.
 * (The [Int] will be converted into 4 bytes)
 */
fun Int.toBytes(order: ByteOrder = ByteOrder.BigEndian): Array<Byte> {
    val result = Array<Byte>(4){0}
    result.updateUseLittleEndian(order){ index ->
         (this shr 8*index).toByte()
    }
    return result
//    val result = ByteArray(4)
//    result[0] = (this shr 24).toByte()
//    result[1] = (this shr 16).toByte()
//    result[2] = (this shr 8).toByte()
//    result[3] = this.toByte()
//    return result.toTypedArray().bigEndianTo(order)
}

private val hexFormat: HexFormat = HexFormat {
    upperCase = true
    number {
        prefix = "0x"
        removeLeadingZeros = true
    }
}


fun Int.toHexStringUse0x(): String =
    toHexString(hexFormat)